using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

namespace CGF
{
    [AddComponentMenu("CGFramework/Reference")]
    public class Reference : MonoBehaviour
    {
        public Node newNode;

        [System.Serializable]
        public class Node { public Object obj; public bool isAsset; }
        public List<Node> nodes = new List<Node>();

        public bool widthComponent = true;

        //如果不生成Reference类，可以直接用节点名字获取对象
        public T Get<T>(object indexOrKey) where T : Object
        {
            if (indexOrKey == null)
            {
                Debug.LogError($"{gameObject.name}.GetNode() 输入的 indexOrKey 为空");
                return default(T);
            }
            if (indexOrKey is int || indexOrKey is byte)
            {
                int index = int.Parse(indexOrKey.ToString());
                if (index < 0 || index > nodes.Count - 1)
                {
                    Debug.LogError($"{gameObject.name}.GetNode() 索引{index}超出范围nodes:{nodes.Count}");
                }
                Node node = nodes[index];
                if (!node.isAsset)
                {
                    if (node.obj.GetType() != typeof(GameObject) || typeof(T) == typeof(GameObject))
                    {
                        return node.obj as T;
                    }
                    T t = (node.obj as GameObject).GetComponent<T>();
                    if (!t)
                    {
                        Debug.LogError($"Reference({gameObject.name}) 的 {node.obj.name} 没有绑定 {typeof(T).Name} 组件");
                        return null;
                    }
                    return t;
                }
                return node.obj as T;
            }
            else if (indexOrKey is string)
            {
                string key = (string)indexOrKey;
                for (int i = 0; i < nodes.Count; i++)
                {
                    Node node = nodes[i];
                    if (node.obj.name.Equals(key))
                    {
                        if (!node.isAsset)
                        {
                            if (node.obj.GetType() != typeof(GameObject) || typeof(T) == typeof(GameObject))
                            {
                                return node.obj as T;
                            }
                            T t = (node.obj as GameObject).GetComponent<T>();
                            if (!t)
                            {
                                Debug.LogError($"Reference({gameObject.name}) 的 {node.obj.name} 没有绑定 {typeof(T).Name} 组件");
                                return null;
                            }
                            return t;
                        }
                        if (typeof(T) == typeof(Sprite) && node.obj is Texture2D)
                        {
                            return TextureHelper.TextureToSprite(node.obj as Texture) as T;
                        }
                        return node.obj as T;
                    }
                }
                Debug.LogError($"{gameObject.name} 上的 Reference 里没有名称为 {indexOrKey} 的映射");
            }
            else
            {
                Debug.LogError($"{gameObject.name}.GetNode() 输入的 indexOrKey 类型错误：{indexOrKey.GetType()}");
            }
            return null;
        }

        public int GetCount()
        {
            return nodes.Count;
        }
    }

    //扩展GameObject和Transform方法，方便读取Reference里的Node
    public static class ReferenceExtand
    {
        public static T Get<T>(this Transform trans, object indexOrKey) where T : Object
        {
            return trans.gameObject.Get<T>(indexOrKey);
        }

        public static T Get<T>(this GameObject go, object indexOrKey) where T : Object
        {
            Reference reference = go.GetComponent<Reference>();
            if (!reference)
            {
                Debug.LogError($"对象 {go.name} 没有绑定 Reference，无法获取 {indexOrKey}");
                return null;
            }
            return reference.Get<T>(indexOrKey);
        }

        ///////////////////////////////////////////////////////////////////

        public static int GetReferenceCount(this Transform trans)
        {
            return trans.gameObject.GetReferenceCount();
        }

        public static int GetReferenceCount(this GameObject go)
        {
            Reference reference = go.GetComponent<Reference>();
            if (!reference)
            {
                Debug.LogError($"对象 {go.name} 没有绑定 Reference，无法获取总数量");
                return 0;
            }
            return reference.GetCount();
        }
    }
}